module top(
    clk,
    rst_n,
    ddr_addr,
    ddr_bank,
    ddr_cs,
    ddr_ras,
    ddr_cas,
    ddr_we,
    ddr_ck,
    ddr_ck_n,
    ddr_cke,
    ddr_odt,
    ddr_reset_n,
    ddr_dm,
    ddr_dq,
    ddr_dqs,
    ddr_dqs_n,
    test_pt,
    state_led,

    test_pin,

    TCK_IN,
    TMS_IN,
    TDI_IN,
    TDO_OUT,

    sdio_dat,
    sdio_cmd,
    sdio_clk,

    ,FLASH_SPI_CSN,
    ,FLASH_SPI_MISO,
    ,FLASH_SPI_MOSI,
    ,FLASH_SPI_CLK,
    ,FLASH_SPI_HOLDN,
    ,FLASH_SPI_WPN,

    UART2_TXD,
    UART2_RXD

);
    input clk;
    output [15-1:0]             ddr_addr;       //ROW_WIDTH=15
    output [3-1:0]              ddr_bank;       //BANK_WIDTH=3
    output                      ddr_cs;
    output                      ddr_ras;
    output                      ddr_cas;
    output                      ddr_we;
    output                      ddr_ck;
    output                      ddr_ck_n;
    output                      ddr_cke;
    output                      ddr_odt;
    output                      ddr_reset_n;
    output [4-1:0]              ddr_dm;         //DM_WIDTH=2
    inout  [16-1:0]             ddr_dq;         //DQ_WIDTH=32
    inout  [4-1:0]              ddr_dqs;        //DQS_WIDTH=2
    inout  [4-1:0]              ddr_dqs_n;      //DQS_WIDTH=2
    input                       rst_n;
    output                      test_pt;
    output                      test_pin;

    output [5:0]                state_led;

    wire                        app_wdf_wren;
    wire  [16-1:0]              app_wdf_mask;    //APP_MASK_WIDTH=16
    wire                        app_wdf_end;
    wire [128-1:0]              app_wdf_data;    //APP_DATA_WIDTH=128
    wire                        app_en;
    wire [2:0]                  app_cmd;
    wire [29-1:0]               app_addr;        //ADDR_WIDTH=29
    wire                        app_sre_req;
    wire                        app_ref_req;
    wire                        app_burst;
    wire                        app_sre_act;
    wire                        app_ref_ack;
    wire                        app_wdf_rdy;
    wire                        app_rdy;
    wire                        app_rd_data_valid;
    wire                        app_rd_data_end;
    wire [128-1:0]              app_rd_data;     //APP_DATA_WIDTH=128
    //assign test_pin = FLASH_SPI_MOSI;

    inout  wire[3:0] sdio_dat;
    inout  wire sdio_cmd;
    output wire sdio_clk;

    input wire  TCK_IN;
    input wire  TMS_IN;
    input wire  TDI_IN;
    output wire TDO_OUT;

    inout FLASH_SPI_CSN;
    inout FLASH_SPI_MISO;
    inout FLASH_SPI_MOSI;
    inout FLASH_SPI_CLK;
    inout FLASH_SPI_HOLDN;
    inout FLASH_SPI_WPN;
    output UART2_TXD;
    input  UART2_RXD;

assign  test_pt = clk_x1;

assign state_led[5] = ~app_wdf_rdy;
assign state_led[4] = ~led;
assign state_led[3] = ~error;
assign state_led[2] = ~pll_stop;
assign state_led[1] = ~pll_lock;
assign state_led[0] = ~init_calib_complete; //DDR3_init_indicator

wire clk;
wire pll_lock;
wire memory_clk;
wire err;
wire clk_x1;
wire clk50m;
wire init_calib_complete;

wire pll_stop;

reg led;

assign error = ~err;
//assign error1 = err;

reg [31:0] led_cnt;

always@(posedge clk_x1)begin // clk_x1 CLK from DDR IP
    if(led_cnt >= 50_000_000) begin
            led <= ~led;
            led_cnt <= 'd0;
    end
    else
            led_cnt <= led_cnt + 1'b1;
end

/////////////////////////////////////////////////////////////////////////////
//AE350

    wire       [31 : 0] cmd_addr;
    wire       [127 : 0] wr_data;
    wire        [127 : 0] lpddr_rd_data = app_rd_data[127:0];
    wire        lpddr_rd_valid          = app_rd_data_valid;
    wire        lpddr_rd_end            = app_rd_data_end;
    wire       [15 : 0] lpddr_wdata_mask;
    wire       lpddr_cmd_en;
    wire       lpddr_cmd;
    wire        lpddr_cmd_ready = app_rdy;
    wire        lpddr_data_ready = app_wdf_rdy;
    wire       lpddr_wdata_en;
    wire       lpddr_wdata_end;

    wire DDR_CLK,CORE_CLK,AHB_CLK,APB_CLK,RTC_CLK;
    wire ae350_rstn;

    //12个信号
    wire [63:0] DDR_HRDATA;
    wire DDR_HREADY;
    wire DDR_HRESP;
    wire [31:0] DDR_HADDR;
    wire [2:0] DDR_HBURST;
    wire [3:0] DDR_HPROT;
    wire [2:0] DDR_HSIZE;
    wire [1:0] DDR_HTRANS;
    wire [63:0] DDR_HWDATA;
    wire DDR_HWRITE;
    wire DDR_HCLK;
    wire DDR_HRSTN;

// // key_debounce instantiation
// // DDR3 memory reset in key debounce
// key_debounce u_key_debounce_ddr3
// (
//     .out(ddr3_rstn),
//     .in(rst_n),
//     .clk(clk_x1),      // 50MHz
//     .rstn(1'b1)
// );


// key_debounce instantiation
// AE350 power on and hardware reset in key debounce
key_debounce u_key_debounce_ae350
(
    .out(ae350_rstn),
    .in(init_calib_complete),
    .clk(clk),              // 50MHz
    .rstn(1'b1)
);

    // Gowin_PLL_AE350 instantiation
Gowin_PLL_AE350 u_Gowin_PLL_AE350
(
    .clkout0(DDR_CLK),          // 50MHz
    .clkout1(CORE_CLK),         // 800MHz
    .clkout2(AHB_CLK),          // 100MHz
    .clkout3(APB_CLK),          // 100MHz
    .clkout4(RTC_CLK),          // 10MHz
    .clkin(clk),
    .enclk0(1'b1),
    .enclk1(1'b1),
    .enclk2(1'b1),
    .enclk3(1'b1),
    .enclk4(1'b1)
);

//gw_ahb_ddr3_top u_gw_ahb_ddr3_top
m_ahb_ddr3 u_gw_ahb_ddr3_top
(
    // DDR3 I/F
    .DDR3_MEMORY_CLK        (memory_clk),   // Memory clock 400MHz
    .DDR3_CLK_IN            (clk50m),       // Clock input 50MHz
    .DDR3_RSTN(rst_n),                      // Reset input
    .DDR3_LOCK(pll_lock),                   // PLL lock
    .DDR3_STOP(pll_stop),                   // PLL stop
    .DDR3_INIT(init_calib_complete),        // Initialized
    //
    // .DDR3_BANK      (DDR3_BANK),
    // .DDR3_CS_N      (DDR3_CS_N),
    // .DDR3_RAS_N     (DDR3_RAS_N),
    // .DDR3_CAS_N     (DDR3_CAS_N),
    // .DDR3_WE_N      (DDR3_WE_N),
    // .DDR3_CK        (DDR3_CK),
    // .DDR3_CK_N      (DDR3_CK_N),
    // .DDR3_CKE       (DDR3_CKE),
    // .DDR3_RESET_N   (DDR3_RESET_N),
    // .DDR3_ODT       (DDR3_ODT),
    // .DDR3_ADDR      (DDR3_ADDR),
    // .DDR3_DM        (DDR3_DM),
    // .DDR3_DQ        (DDR3_DQ),
    // .DDR3_DQS       (DDR3_DQS),
    // .DDR3_DQS_N     (DDR3_DQS_N),
    // AHB bus I/F
    .HCLK(DDR_HCLK),
    .HRESETN(DDR_HRSTN),
    .HADDR(DDR_HADDR),
    .HSIZE(DDR_HSIZE),
    .HWRITE(DDR_HWRITE),
    .HTRANS(DDR_HTRANS),
    .HBURST(DDR_HBURST),
    .HWDATA(DDR_HWDATA),
    .HREADY_O(DDR_HREADY),
    .HRESP(DDR_HRESP),
    .HRDATA(DDR_HRDATA),


    //AHB总线操作memory
    .ddr_clk            (clk_x1),
    .cmd_addr           (cmd_addr        ),
    .wr_data            (wr_data         ),
    .lpddr_rd_data      (lpddr_rd_data   ),
    .lpddr_rd_valid     (lpddr_rd_valid  ),
    .lpddr_rd_end       (lpddr_rd_end    ),
    .lpddr_wdata_mask   (lpddr_wdata_mask),
    .lpddr_cmd_en       (lpddr_cmd_en    ),
    .lpddr_cmd          (lpddr_cmd       ),
    .lpddr_cmd_ready    (lpddr_cmd_ready ),
    .lpddr_data_ready   (lpddr_data_ready),
    .lpddr_wdata_en     (lpddr_wdata_en  ),
    .lpddr_wdata_end    (lpddr_wdata_end )
);

    wire[31:0]  APB_PRDATA ;
    wire        APB_PREADY ;
    wire        APB_PSLVERR;
    wire[31:0]  APB_PADDR ;
    wire        APB_PENABLE;
    wire        APB_PSEL ;
    wire[31:0]  APB_PWDATA ;
    wire        APB_PWRITE ;
    wire[2:0]   APB_PPROT ;
    wire[3:0]   APB_PSTRB ;
    wire        APB_PCLK ;
    wire        APB_PRSTN ;

    // sdio_fifo u_sdio_fifo(
	// 	.Data(fifo_write_data), //input [31:0] Data
	// 	.WrReset(fifo_write_rst), //input WrReset
	// 	.RdReset(fifo_read_rst), //input RdReset
	// 	.WrClk(APB_PCLK), //input WrClk
	// 	.RdClk(APB_PCLK), //input RdClk
	// 	.WrEn(fifo_write_en), //input WrEn
	// 	.RdEn(fifo_read_en), //input RdEn
	// 	.Almost_Empty(), //output Almost_Empty
	// 	.Almost_Full(), //output Almost_Full
	// 	.Q(fifo_read_data), //output [31:0] Q
	// 	.Empty(fifo_empty), //output Empty
	// 	.Full() //output Full
	// );

    // wire        fifo_empty;
    // wire[31:0]  fifo_read_data;
    // wire[31:0]  fifo_write_data;
    // wire fifo_write_en;
    // wire fifo_write_rst;
    // wire fifo_read_en;
    // wire fifo_read_rst;

    // sdio u_sdio(
    //     .fifo_write_data     (fifo_write_data),
    //     .fifo_write_en       (fifo_write_en  ),
    //     .fifo_write_rst      (fifo_write_rst ),

    //     .fifo_read_data      (fifo_read_data),
    //     .fifo_read_en        (fifo_read_en  ),
    //     .fifo_read_rst       (fifo_read_rst ),
    //     .fifo_empty          (fifo_empty),

    //     .clk            (APB_PCLK),
    //     .rstn           (APB_PRSTN),

    //     .sdio_dat       (sdio_dat),
    //     .sdio_cmd       (sdio_cmd),
    //     .sdio_clk       (sdio_clk),

    //     .apb_addr       (APB_PADDR),
    //     .apb_hwdata     (APB_PWDATA),
    //     .apb_hrdata     (APB_PRDATA),
    //     .apb_hwrite     (APB_PWRITE),
    //     .apb_htran      (APB_PENABLE ^ APB_PSEL),
    //     .apb_hready_o   (APB_PREADY),
    //     .apb_hsel       (APB_PSEL && (APB_PADDR[23:16]=='h00))      //$f8000000
    // );
`define USE_NEW_SDIO
`ifndef USE_NEW_SDIO
    wire            fifo_send_wren;
    wire            fifo_send_rden;
    wire            fifo_send_emty;
    wire            fifo_send_full;
    wire            fifo_send_rst;
    wire[39:0]      fifo_send_data;
    wire[39:0]      fifo_send_data_i;

    wire            fifo_recv_wren ;
    wire            fifo_recv_rden ;
    wire            fifo_recv_emty ;
    wire            fifo_recv_full ;
    wire            fifo_recv_rst  ;
    wire[31:0]      fifo_recv_data_o;
    wire[31:0]      fifo_recv_data_i;

    sdio_fifo_send u_sdio_send_fifo(
		.Data       (fifo_send_data), //input [31:0] Data
		.WrReset    (fifo_send_rst), //input WrReset
		.RdReset    (fifo_send_rst), //input RdReset
        .WrEn       (fifo_send_wren), //input WrEn
		.RdEn       (fifo_send_rden), //input RdEn
		.Q          (fifo_send_data_i), //output [31:0] Q
		.Empty      (fifo_send_emty), //output Empty
        .Full       (fifo_send_full), //output Full

		.WrClk      (APB_PCLK), //input WrClk
		.RdClk      (APB_PCLK), //input RdClk
        .Almost_Empty(), //output Almost_Empty
		.Almost_Full() //output Almost_Full
    );

    sdio_fifo u_sdio_recv_fifo(
		.Data       (fifo_recv_data_o), //input [31:0] Data
		.WrReset    (fifo_recv_rst), //input WrReset
		.RdReset    (fifo_recv_rst), //input RdReset
        .WrEn       (fifo_recv_wren), //input WrEn
		.RdEn       (fifo_recv_rden), //input RdEn
		.Q          (fifo_recv_data_i), //output [31:0] Q
		.Empty      (fifo_recv_emty), //output Empty
        .Full       (fifo_recv_full), //output Full

		.WrClk      (APB_PCLK), //input WrClk
		.RdClk      (APB_PCLK), //input RdClk
        .Almost_Empty(), //output Almost_Empty
		.Almost_Full() //output Almost_Full
    );


    ftsdc010_mmc_sim u_mmc(
        .fifo_send_wren     (fifo_send_wren     ),
        .fifo_send_data     (fifo_send_data     ),
        .fifo_send_data_i   (fifo_send_data_i   ),
        .fifo_send_rden     (fifo_send_rden     ),
        .fifo_send_emty     (fifo_send_emty     ),
        .fifo_send_full     (fifo_send_full     ),
        .fifo_send_rst      (fifo_send_rst      ),

        .fifo_recv_wren     (fifo_recv_wren  ),
        .fifo_recv_data_o   (fifo_recv_data_o),
        .fifo_recv_data_i   (fifo_recv_data_i),
        .fifo_recv_rden     (fifo_recv_rden  ),
        .fifo_recv_emty     (fifo_recv_emty  ),
        .fifo_recv_full     (fifo_recv_full  ),
        .fifo_recv_rst      (fifo_recv_rst   ),

        .sdio_dat           (sdio_dat),
        .sdio_cmd           (sdio_cmd),
        .sdio_clk           (sdio_clk),
        .clk                (APB_PCLK),
        .rstn               (APB_PRSTN),

        .apb_addr           (APB_PADDR),
        .apb_pwdata         (APB_PWDATA),
        .apb_prdata         (APB_PRDATA),
        .apb_pwrite         (APB_PWRITE),
        .apb_ptran          (APB_PENABLE ^ APB_PSEL),
        .apb_pready_o       (APB_PREADY),
        .apb_psel           (APB_PSEL && (APB_PADDR[23:16]=='h00))      //$f8000000
    );

`endif //USE_NEW_SDIO

`ifdef USE_NEW_SDIO

ftsdc010_sim u_ftsdc010(
    .sdio_clk       (sdio_clk),
    .sdio_cmd       (sdio_cmd),
    .sdio_dat       (sdio_dat),
    .apb_psel       (APB_PSEL && (APB_PADDR[23:16]=='h00)),
    .apb_addr       (APB_PADDR),
    .apb_pwdata     (APB_PWDATA),
    .apb_prdata     (APB_PRDATA),
    .apb_pwrite     (APB_PWRITE),
    .apb_ptran      (APB_PENABLE ^ APB_PSEL),
    .apb_pready_o   (APB_PREADY),
    .clk            (APB_PCLK),
    .reset          (~APB_PRSTN)
);

`endif

RiscV_AE350_SOC_Top u_RiscV_AE350_SOC_Top
(
    .FLASH_SPI_CSN      (/*FLASH_SPI_CSN  */    ),
    .FLASH_SPI_MISO     (/*FLASH_SPI_MISO */    ),
    .FLASH_SPI_MOSI     (/*FLASH_SPI_MOSI */    ),
    .FLASH_SPI_CLK      (/*FLASH_SPI_CLK  */    ),
    .FLASH_SPI_HOLDN    (/*FLASH_SPI_HOLDN*/    ),
    .FLASH_SPI_WPN      (/*FLASH_SPI_WPN  */    ),

    .SPI_HOLDN  (FLASH_SPI_HOLDN),
    .SPI_WPN    (FLASH_SPI_WPN),
    .SPI_CLK    (FLASH_SPI_CLK),
    .SPI_CSN    (FLASH_SPI_CSN),
    .SPI_MISO   (FLASH_SPI_MISO),
    .SPI_MOSI   (FLASH_SPI_MOSI),

    //12个信号
    .DDR_HRDATA(DDR_HRDATA),
    .DDR_HREADY(DDR_HREADY),
    .DDR_HRESP(DDR_HRESP),
    .DDR_HADDR(DDR_HADDR),
    .DDR_HBURST(DDR_HBURST),
    .DDR_HPROT(DDR_HPROT),
    .DDR_HSIZE(DDR_HSIZE),
    .DDR_HTRANS(DDR_HTRANS),
    .DDR_HWDATA(DDR_HWDATA),
    .DDR_HWRITE(DDR_HWRITE),
    .DDR_HCLK(DDR_HCLK),
    .DDR_HRSTN(DDR_HRSTN),


    .APB_PRDATA(APB_PRDATA), //input [31:0] APB_PRDATA
    .APB_PREADY(APB_PREADY), //input APB_PREADY
    .APB_PSLVERR(APB_PSLVERR), //input APB_PSLVERR
    .APB_PADDR(APB_PADDR), //output [31:0] APB_PADDR
    .APB_PENABLE(APB_PENABLE), //output APB_PENABLE
    .APB_PSEL(APB_PSEL), //output APB_PSEL
    .APB_PWDATA(APB_PWDATA), //output [31:0] APB_PWDATA
    .APB_PWRITE(APB_PWRITE), //output APB_PWRITE
    .APB_PPROT(APB_PPROT), //output [2:0] APB_PPROT
    .APB_PSTRB(APB_PSTRB), //output [3:0] APB_PSTRB
    .APB_PCLK(APB_PCLK), //output APB_PCLK
    .APB_PRSTN(APB_PRSTN), //output APB_PRSTN

    //6个信号
    .TCK_IN(TCK_IN),
    .TMS_IN(TMS_IN),
    .TRST_IN(1'b1),
    .TDI_IN(TDI_IN),
    .TDO_OUT(TDO_OUT),
    .TDO_OE(),

    .UART2_TXD(UART2_TXD),
    .UART2_RTSN(),
    .UART2_RXD(UART2_RXD),
    .UART2_CTSN(),
    .UART2_DCDN(),
    .UART2_DSRN(),
    .UART2_RIN(),
    .UART2_DTRN(),
    .UART2_OUT1N(),
    .UART2_OUT2N(),
    .GPIO(),
    .CORE_CLK(CORE_CLK),
    .DDR_CLK(DDR_CLK),
    .AHB_CLK(AHB_CLK),
    .APB_CLK(APB_CLK),
    .RTC_CLK(RTC_CLK),
    //
    .POR_RSTN(ae350_rstn),              // AE350 CPU core power on reset, 0 is reset state
    .HW_RSTN(ae350_rstn)                // AE350 hardware reset, 0 is reset state
);

/////////////////////////////////////////////////////////////////////////////


Gowin_PLL Gowin_PLL_inst(
.lock(pll_lock),
.clkout0(),
.clkout1(clk50m),
.clkout2(memory_clk),
.clkin(clk),
.reset(1'b0),
.enclk0(1'b1), //input enclk0
.enclk1(1'b1), //input enclk1
.enclk2(pll_stop) //input enclk2
);

ddr3_test1  #
    (
     .ADDR_WIDTH(29) ,          //ADDR_WIDTH=29
     .APP_DATA_WIDTH(128) ,     //APP_DATA_WIDTH=128
     .APP_MASK_WIDTH (16),      //APP_MASK_WIDTH=16
     .USER_REFRESH("OFF")
    )u_rd(
    .clk                (clk_x1),
    .rst                (~rst_n),
    .app_rdy            (app_rdy),
    .app_en             (app_en),
    .app_cmd            (app_cmd),
    .app_addr           (app_addr),
    .app_wdf_data       (app_wdf_data),
    .app_wdf_wren       (app_wdf_wren),
    .app_wdf_end        (app_wdf_end),
    .app_wdf_mask       (app_wdf_mask),
    .app_burst          (app_burst),
    .app_rd_data_valid  (app_rd_data_valid),
    .app_rd_data        (app_rd_data),
    .init_calib_complete(init_calib_complete),
    .wr_data_rdy        (app_wdf_rdy),
    .sr_req             (sr_req),
    .error              (err),
    .ref_req            (ref_req)
    );

//DDR3_Memory_Interface_Top u_ddr3 (
    D3_400 u_ddr3 (
    .memory_clk      (memory_clk        ),
    .pll_stop        (pll_stop          ),
    .clk             (clk50m            ),   //clkout0->DDR3_CLK_IN->ddr_clk_in->memory_top.clk
    .rst_n           (rst_n             ),   //rst_n
    .sr_req          (1'b0              ),
    .ref_req         (1'b0              ),
    //.zq_req          (1'b0),
    .sr_ack          (app_sre_act       ),
    .ref_ack         (app_ref_ack       ),
    .clk_out         (clk_x1            ),
    .pll_lock        (pll_lock          ),
    //.pll_lock        (1'b1),
    //`ifdef ECC
    //.ecc_err         (ecc_err),
    //`endif
    .init_calib_complete(init_calib_complete),

    //需要更改
    .cmd_ready       (app_rdy) /*app_rdy               )*/,          //o
    .cmd             (/*!init_calib_complete*/1'b0 ? app_cmd           :  {2'b00,lpddr_cmd}              ) /*app_cmd               )*/,          //i[2:0]
    .cmd_en          (/*!init_calib_complete*/1'b0 ? app_en            :  lpddr_cmd_en                   ) /*app_en                )*/,          //i
    .addr            (/*!init_calib_complete*/1'b0 ? app_addr          :  {3'b000,cmd_addr[25:3],3'b000}  ) /*app_addr              )*/,          //i[addr:0]
    .wr_data_rdy     (app_wdf_rdy) /*app_wdf_rdy           )*/,          //o
    .wr_data         (/*!init_calib_complete*/1'b0 ? app_wdf_data      :  {wr_data}                      ) /*app_wdf_data          )*/,          //i[data:0]
    .wr_data_en      (/*!init_calib_complete*/1'b0 ? app_wdf_wren      :  lpddr_wdata_en                 ) /*app_wdf_wren          )*/,          //i
    .wr_data_end     (/*!init_calib_complete*/1'b0 ? app_wdf_end       :  lpddr_wdata_end                ) /*app_wdf_end           )*/,          //i
    .wr_data_mask    (/*!init_calib_complete*/1'b0 ? app_wdf_mask      :  {lpddr_wdata_mask}             ) /*app_wdf_mask          )*/,          //i[mask:0]
    .rd_data         ( app_rd_data       ) /*app_rd_data           )*/,          //o[data:0]
    .rd_data_valid   ( app_rd_data_valid ) /*app_rd_data_valid     )*/,          //o
    .rd_data_end     ( app_rd_data_end   ) /*app_rd_data_end       )*/,          //o

    .burst           (1'b1     ),
    // mem interface,不用更改
    .ddr_rst         (ddr_rst       ),
    .O_ddr_addr      (ddr_addr      ),
    .O_ddr_ba        (ddr_bank      ),
    .O_ddr_cs_n      (ddr_cs        ),
    .O_ddr_ras_n     (ddr_ras       ),
    .O_ddr_cas_n     (ddr_cas       ),
    .O_ddr_we_n      (ddr_we        ),
    .O_ddr_clk       (ddr_ck        ),
    .O_ddr_clk_n     (ddr_ck_n      ),
    .O_ddr_cke       (ddr_cke       ),
    .O_ddr_odt       (ddr_odt       ),
    .O_ddr_reset_n   (ddr_reset_n   ),
    .O_ddr_dqm       (ddr_dm        ),
    .IO_ddr_dq       (ddr_dq        ),
    .IO_ddr_dqs      (ddr_dqs       ),
    .IO_ddr_dqs_n    (ddr_dqs_n     )
);
endmodule
